﻿/***********************************************************************
 * <copyright file="AOnlineServiceDto.cs" company="BUCA JSC">
 * -->    Copyright (C) statement. All right reserved
 * </copyright>
 * 
 * Created:   Tuanhm
 * Email:    Tuanhm@humg@gmail.com
 * Website:
 * Create Date: Thursday, March 27, 2014
 * Usage: 
 * 
 * RevisionHistory: 
 * Date         Author               Description 
 * 
 * ************************************************************************/

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Web;
using AOnlineService.ServiceContracts;
using AOnlineService.Messages;
using AOnlineService.MessageBase;
using DataObjects;
using DataObjects.Shared;
using DataObjects.StandartInterfaces.Dictionary;
using AOnlineService.Messages.Dictionary;
using AOnlineService.DataTransferObjectMapper;

namespace AOnlineService.ServiceImplementations 
{
    /// <summary>
    /// Main facade into Patterns in Action application.
    /// Important: Each Session has its own instance of this class (see ServiceBehavior Attribute).
    /// </summary>
    /// <remarks>
    /// Application Facade Pattern.
    /// </remarks>
    [ServiceContract(SessionMode = SessionMode.Allowed)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class AOnlineDictionaryService : IAOnlineDictionaryService   
    {
        //Create static data access objects
        private static readonly IEmployTest EmployTestDao = DataAccess.EmployTestDao;        
        private static readonly IAccountDao AccountDao = DataAccess.AccountDao;
     
        // Session state variables  >
        /// <summary>
        /// The _access token
        /// </summary>
        private static string _accessToken;
        /// <summary>
        /// The _unit identifier
        /// </summary>
        public static long _unitId = 1;
      //  {
            //get
            //{
            //    var unitIdSession = HttpContext.Current.Session["FA-BigTime.UnitId"];
            //    return unitIdSession == null ? 0 : (long)unitIdSession;
            //}
            //set
            //{
            //    HttpContext.Current.Session["FA-BigTime.UnitId"] = value;
            //}
     //   }
        /// <summary>
        /// Gets or sets the name of the _unit.
        /// </summary>
        /// <value>
        /// The name of the _unit.
        /// </value>
        public static string _unitName
        {
            get
            {
                var unitNameSession = HttpContext.Current.Session["FA-BigTime.UnitName"];
                return unitNameSession == null ? "" : unitNameSession.ToString();
            }
            set
            {
                HttpContext.Current.Session["FA-BigTime.UnitName"] = value;
            }
        }
        public static string userId
        {
            get
            {
                var unitNameSession = HttpContext.Current.Session["FA-BigTime.UserId"];
                return unitNameSession == null ? "" : unitNameSession.ToString();
            }
            set
            {
                HttpContext.Current.Session["FA-BigTime.UserId"] = value;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AOnlineService"/> class.
        /// </summary>

        /// <summary>
        /// Gets unique session based token that is valid for the duration of the session.
        /// </summary>
        /// <param name="request">Token request message.</param>
        /// <returns>Token response message.</returns>
        public TokenResponse GetToken(TokenRequest request)
        {
            var response = new TokenResponse(request.RequestId);

            // Validate client tag only
            if (!ValidRequest(request, response, Validate.ClientTag))
                return response;

            // Note: these are session based and expire when session expires.
            _accessToken = Guid.NewGuid().ToString();
            //_shoppingCart = new ShoppingCart(_defaultShippingMethod);
            response.AccessToken = _accessToken;
            return response;
        }
        #region Security
      
        #endregion

        #region Dictionary
        public EmployTestResponse GetEmployTests(EmployTestRequest request)
        {
            var response = new EmployTestResponse(request.RequestId);
            var criteria = request.Criteria;

            if (!ValidRequest(request, response, Validate.All))
                return response;

            if (request.LoadOptions != null)
            {
                if (request.LoadOptions.Contains("EmployTests")) //get list of EmployTest
                {
                    if ((OptionType.IsUnit & request.Options) == OptionType.IsUnit) //get by unit & paging || non-paging
                    {
                        if ((OptionType.IsPaging & request.Options) == OptionType.IsPaging)
                        {
                            var EmployTests = EmployTestDao.GetPaged(_unitId.AsInt(), request.CurrentPage);
                            response.EmployTests = Mapper.ToDataTransferObjects(EmployTests);
                        }
                        else
                        {
                            if ((OptionType.IsActive & request.Options) == OptionType.IsActive)
                            {
                            //    var EmployTests = EmployTestDao.GetEmployTestsByUnit(_unitId.AsInt());
                            //    response.EmployTests = Mapper.ToDataTransferObjects(EmployTests);
                            }
                            else
                            {
                           //     var EmployTests = EmployTestDao.GetEmployTestsByUnit(_unitId.AsInt());
                           //     response.EmployTests = Mapper.ToDataTransferObjects(EmployTests);
                            }
                        }
                    }
                    //else //get all
                    //{
                    //    var EmployTests = EmployTestDao.GetEmployTests();
                    //    response.EmployTests = Mapper.ToDataTransferObjects(EmployTests);
                    //}
                }

                if (request.LoadOptions.Contains("EmployTest")) //get EmployTest by id
                {
                        var EmployTest = EmployTestDao.GetEmployTest(criteria.EmployTestId);
                        response.EmployTest = Mapper.ToDataTransferObject(EmployTest); 
                }

                if (request.LoadOptions.Contains(("TotalPage")))
                {
                    var totalPage = EmployTestDao.GetPageSize(_unitId.AsInt());
                    response.TotalPage = totalPage;
                }
            }
            return response;
        }
        /// <summary>EmployTest
        /// Set (add, update, delete) customer value.
        /// </summary>
        /// <param name="request">EmployTest request message.</param>
        /// <returns>EmployTest response message.</returns>
        public EmployTestResponse SetEmployTests(EmployTestRequest request)
        {
            var response = new EmployTestResponse(request.RequestId);
            string errorMessage = null;

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;
            if (request.EmployTest != null)
            {
                //request.EmployTest.UnitId = _unitId;
                //request.EmployTest.IsSystem = false;
            }
            // Transform customer data transfer object to customer business object
            var employTest = Mapper.FromDataTransferObject(request.EmployTest); 

            // Validate customer business rules
            if (request.Action != "Delete")
            {
                if (!employTest.Validate())
                {
                    response.Acknowledge = AcknowledgeType.Failure;

                    foreach (var error in employTest.ValidationErrors)
                        response.Message += error + Environment.NewLine;

                    return response;
                }
            }

            try
            {
                switch (request.Action)
                {
                    case "Create":
                        errorMessage = EmployTestDao.InsertEmployTest(employTest);
                        break;
                    case "Update":
                        errorMessage = EmployTestDao.UpdateEmployTest(employTest);
                        break;
                    case "Delete":
                         var criteria = request.Criteria;
                         var employForDelete = EmployTestDao.GetEmployTest(criteria.EmployTestId);                       
                         errorMessage = EmployTestDao.DeleteEmployTest(employForDelete);                       
                        break;
                }
                if (errorMessage == null)
                {
                    response.Acknowledge = AcknowledgeType.Success;
                    response.EmployTest = Mapper.ToDataTransferObject(employTest);
                }
                else
                {
                    response.Acknowledge = AcknowledgeType.Failure;
                    response.Message = errorMessage;
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
            }

            return response;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public AccountResponse GetAccounts(AccountRequest request)
        {
            var response = new AccountResponse(request.RequestId);
            var criteria = request.Criteria;

            if (!ValidRequest(request, response, Validate.All))
                return response;

            if (request.LoadOptions.Contains("Accounts")) //get list of BudgetSourcesProperty
            {
                if ((OptionType.IsUnit & request.Options) == OptionType.IsUnit) //get by unit & paging || non-paging
                {
                    if ((OptionType.IsPaging & request.Options) == OptionType.IsPaging)
                    {
                        var accounts = AccountDao.GetPaged(_unitId.AsInt(),  request.CurrentPage);
                        var totalPage = AccountDao.GetPageSize(_unitId.AsInt());
                        response.TotalPage = totalPage;
                        response.Accounts = Mapper.ToDataTransferObjects(accounts);
                    }
                    else 
                    {
                        if (request.LoadOptions.Contains("ForComboTree"))
                        {
                            var accounts =  AccountDao.GetAccountsForComboTree(_unitId.AsInt());
                            response.Accounts = Mapper.ToDataTransferObjects(accounts);
                        }
                        else
                        {
                            //var accounts =  AccountDao.GetAccountsByUnit(_unitId.AsInt());
                            //response.Accounts = Mapper.ToDataTransferObjects(accounts);
                        }
                    }
                }
                else //get all
                {
                    //var accounts = AccountDao.GetAccounts();
                    //response.Accounts = Mapper.ToDataTransferObjects(accounts);
                }
            }

            if (request.LoadOptions.Contains("Account")) //get budgetSource by id
            {
                var Account = AccountDao.GetAccount(criteria.AccountId);
                response.Account = Mapper.ToDataTransferObject(Account);
            }
            if (request.LoadOptions.Contains(("TotalPage")))
            {
                var totalPage = AccountDao.GetPageSize(_unitId.AsInt());
                response.TotalPage = totalPage;
            }
            return response;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public AccountResponse SetAccounts(AccountRequest request)
        {

            var response = new AccountResponse(request.RequestId);
            string errorMessage = null;

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;
            if (request.Account != null)
            {
                request.Account.UnitId = _unitId;
            }
            // Transform customer data transfer object to customer business object
            var Account = Mapper.FromDataTransferObject(request.Account);

            // Validate customer business rules
            if (request.Action != "Delete")
            {
                if (!Account.Validate())
                {
                    response.Acknowledge = AcknowledgeType.Failure;

                    foreach (var error in Account.ValidationErrors)
                        response.Message += error + Environment.NewLine;

                    return response;
                }
            }
            try
            {
                switch (request.Action)
                {
                    case "Create":
                        errorMessage = AccountDao.InsertAccount(Account);
                        break;
                    case "Update":
                        errorMessage = AccountDao.UpdateAccount(Account);
                        break;
                    case "Delete":
                        var criteria = request.Criteria;
                        var AccountDelete =
                            AccountDao.GetAccount(criteria.AccountId);
                        if (AccountDelete == null)
                        {
                            response.Acknowledge = AcknowledgeType.Failure;
                            response.Message = "Không thể xóa ! Dữ liệu không còn tồn tại trong hệ thống !";
                            return response;
                        }
                        //check child
                        var child =  AccountDao.GetAccountsByParent( criteria.AccountId).Count;
                        if (child == 0)
                        {
                            response.Acknowledge = AcknowledgeType.Success;
                            errorMessage =
                                AccountDao.DeleteAccount(AccountDelete);
                        }
                        else
                        {
                            response.Acknowledge = AcknowledgeType.Failure;
                            response.Message = "Không thể xóa ! Nhóm TK đã có TK con !";
                            return response;
                        }
                        break;
                }
                if (errorMessage == null)
                {
                    response.Acknowledge = AcknowledgeType.Success;
                    response.Account = Mapper.ToDataTransferObject(Account);
                }
                else
                {
                    response.Acknowledge = AcknowledgeType.Failure;
                    response.Message = errorMessage;
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
            }

            return response;
        }
        #endregion


        /// <summary>
        /// Validate 3 security levels for a request: ClientTag, AccessToken, and User Credentials
        /// </summary>
        /// <param name="request">The request message.</param>
        /// <param name="response">The response message.</param>
        /// <param name="validate">The validation that needs to take place.</param>
        /// <returns></returns>
        private bool ValidRequest(RequestBase request, ResponseBase response, Validate validate)
        {
            // Validate Client Tag. 
            // Hardcoded here. In production this should query a 'client' table in a database.
            if ((Validate.ClientTag & validate) == Validate.ClientTag)
            {
                if (request.ClientTag != "ABC123")
                {
                    response.Acknowledge = AcknowledgeType.Failure;
                    response.Message = "Unknown Client Tag";
                    return false;
                }
            }
            var token = _accessToken;
            //validate unitId
            //if ((Validate.UnitId & validate) == Validate.UnitId)
            //{
            //    if (_unitId == 0)
            //    {
            //        response.Acknowledge = AcknowledgeType.Failure;
            //        response.Message = "Please login and provide unit before accessing these methods";
            //        return false;
            //    }
            //}
            return true;
        }
        /// <summary>
        /// Valids the anymouse request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="response">The response.</param>
        /// <param name="validate">The validate.</param>
        /// <returns></returns>
        private bool ValidAnymouseRequest(RequestBase request, ResponseBase response, Validate validate)
        {
            // Validate Client Tag. 
            // Hardcoded here. In production this should query a 'client' table in a database.
            if ((Validate.ClientTag & validate) == Validate.ClientTag)
            {
                if (request.ClientTag != "ABC123")
                {
                    response.Acknowledge = AcknowledgeType.Failure;
                    response.Message = "Unknown Client Tag";
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// Validation options enum. Used in validation of messages.
        /// </summary>
        [Flags]
        private enum Validate
        {
            ClientTag = 0x0001,
            AccessToken = 0x0002,
            UserCredentials = 0x0004,
            UnitId = 0x0008,
            All = ClientTag | AccessToken | UserCredentials | UnitId
        }



        public DepartmentTestResponse GetDepartmentTests(DepartmentTestRequest request)
        {
            throw new NotImplementedException();
        }

        public DepartmentTestResponse SetDepartmentTests(DepartmentTestRequest request)
        {
            throw new NotImplementedException();
        }
    }
}